/*******************************************************************************
 * $Header: /cvsroot/oloa/org.gocom.bpm.platform.model/src/org/gocom/bpm/platform/model/web/DefaultProcessObjectProvider.java,v 1.1 2011/07/03 02:30:49 hufulai Exp $
 * $Revision: 1.1 $
 * $Date: 2011/07/03 02:30:49 $
 *
 *==============================================================================
 *
 * Copyright (c) 2001-2006 Primeton Technologies, Ltd.
 * All rights reserved.
 * 
 * Created on 2010-5-26
 *******************************************************************************/


package com.atozsoft.wf.web;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.primeton.workflow.api.DefinationCatcheService;
import com.primeton.workflow.api.IWFInstancePool;
import com.primeton.workflow.api.PageCond;
import com.primeton.workflow.api.WFServiceException;
import com.primeton.workflow.commons.utility.StringUtil;
import com.primeton.workflow.instpool.versionsync.InstPoolSync;
import com.primeton.workflow.model.OrderCond;
import com.primeton.workflow.model.definition.Activity;
import com.primeton.workflow.model.definition.WFProcess;
import com.primeton.workflow.service.das.DataAccessService;
import com.primeton.workflow.service.das.exception.DataAccessException;
import com.primeton.workflow.service.das.model.entities.WFActivityInstInternal;
import com.primeton.workflow.service.das.model.entities.WFProcessDefineInternal;
import com.primeton.workflow.service.das.model.entities.WFProcessInstInternal;
import com.primeton.workflow.service.das.model.entities.WFTransCtrl;
import com.primeton.workflow.service.framework.WFServiceFactory;
import com.atozsoft.wf.taglib.Connection;
import com.atozsoft.wf.taglib.State;
import com.atozsoft.wf.taglib.StateImpl;

public class DefaultProcessObjectProvider implements IProcessObjectProvider{

	public ProcessObject getProcessObject(long processInstID,String processName,long processDefID) {

        DataAccessService das = WFServiceFactory.getService(DataAccessService.class);
        WFProcessDefineInternal procDefInternal = null;
        WFProcessInstInternal procInstInternal=null;
        int strategy=0;
        WFProcess process=null;
        ProcessObject processObject=new ProcessObject();
        try
        {
            if(processInstID > 0L)
            {
                InstPoolSync.INSTANCE.sync(processInstID);
                
                procInstInternal = WFServiceFactory.getService(IWFInstancePool.class).findProcessInstanceByID(processInstID);
                if(procInstInternal == null){
                    procInstInternal = das.findProcessInstanceByID(processInstID, 1);
                    strategy = 1;
                }
                if(procInstInternal != null){
                    process = WFServiceFactory.getService(DefinationCatcheService.class).getProcessDefine(procInstInternal.getProcessDefID());
                    long _processDefID = procInstInternal.getProcessDefID();
                    
                    processObject.setProcess(process);
                    processObject.setProcessInstID(processInstID);
                    processObject.setProcessDefID(_processDefID);
                    processObject.setStrategy(strategy);
                    processObject.setProcessInstName(procInstInternal.getProcessInstName());
                }

            } else if(StringUtil.isNotNullAndBlank(processName)){
                procDefInternal = das.findLastProcessDefineByName(processName);
                long _processDefID = procDefInternal.getProcessDefID().longValue();
                
                if(procDefInternal != null && _processDefID > 0L){
                    process = WFServiceFactory.getService(DefinationCatcheService.class).getProcessDefine(_processDefID);
                
	                processObject.setProcess(process);
	                processObject.setProcessDefID(_processDefID);
	                processObject.setStrategy(strategy);
                }
                
            } else if(processDefID > 0L){
                process = WFServiceFactory.getService(DefinationCatcheService.class).getProcessDefine(processDefID);
                
                processObject.setProcess(process);
                processObject.setProcessDefID(processDefID);
                processObject.setStrategy(strategy);
            }
        }
        catch(Exception e){
            e.printStackTrace();
            return null;
        }
        
		return processObject;
	}

	public void transform2ProcessInstGraph(List<Connection> connections, Map<String, State> states, ProcessObject processObject) {
		try {
			transformConnections(connections, processObject);
			transformStates(states, processObject);
		} catch (WFServiceException e) {
			e.printStackTrace();
		}
		
	}

    private void transformStates(Map<String,State> states,ProcessObject processObject)throws WFServiceException
    {
        WFActivityInstInternal activityInstInternals[];
        if(processObject.getStrategy() == 0)
            activityInstInternals = getActInstsFromRunning(processObject);
        else
            activityInstInternals = getActInstsFromHistory(processObject);
        
        for(int i = activityInstInternals.length - 1; i >= 0; i--)
        {
            StateImpl stat = (StateImpl)states.get(activityInstInternals[i].getActivityDefID());
            if(stat == null)
                continue;
            if(activityInstInternals[i].getCurrentState() > 0x80000001)
                if(activityInstInternals[i].getCurrentState() == 2 || activityInstInternals[i].getCurrentState() == 7)
                {
                    stat.setCurrentState((new StringBuilder()).append(String.valueOf(activityInstInternals[i].getCurrentState())).append('_').append(String.valueOf(activityInstInternals[i].getRollbackFlag())).toString());
                    if(activityInstInternals[i].getCurrentState() == 7)
                    {
                        for(int k = activityInstInternals.length - 1; k >= 0; k--)
                            if(activityInstInternals[i].getActivityDefID() == activityInstInternals[k].getActivityDefID() && activityInstInternals[k].getCurrentState() == 2)
                                stat.setCurrentState((new StringBuilder()).append(String.valueOf(activityInstInternals[k].getCurrentState())).append('_').append(String.valueOf(activityInstInternals[k].getRollbackFlag())).toString());

                    }
                } else
                {
                    stat.setCurrentState(String.valueOf(activityInstInternals[i].getCurrentState()));
                }
            stat.setId(String.valueOf(activityInstInternals[i].getActivityInstID()));
            stat.setName(activityInstInternals[i].getActivityInstName());
            stat.getExtendAttribute().put("processInstId", processObject.getProcessInstID());
            stat.getExtendAttribute().put("activityInstId", Long.valueOf(activityInstInternals[i].getActivityInstID()));
            stat.getExtendAttribute().put("processInstId", processObject.getProcessInstID());
        }

    }

    private void transformConnections(List<Connection> connections,ProcessObject processObject)throws WFServiceException
    {
        WFTransCtrl transCtrls[] = null;
        if(processObject.getStrategy() == 1)
            transCtrls = findAllTransCtrlFromHistory(processObject);
        else
            transCtrls = findAllTransCtrlFromRunning(processObject);
        
        for(int i = 0; i < connections.size(); i++)
        {
            Connection ci = (Connection)connections.get(i);
            WFTransCtrl tranCtrl = findTransCtrlInArr(transCtrls, ci.getFromState().getId(), ci.getToState().getId());
            if(tranCtrl == null){
                ci.setType(0);
                continue;
            }
            
            if(tranCtrl.getTransWeight() == 0)
                ci.setType(1);
            if(tranCtrl.getTransWeight() > 0)
                ci.setType(2);
        }

    }

    private WFActivityInstInternal[] getActInstsFromHistory(ProcessObject processObject) throws WFServiceException
    {
        List activityDefines = processObject.getProcess().getActivitys();
        List activityInsts = new ArrayList();
        Iterator it = activityDefines.iterator();
        while(it.hasNext()){
            Activity activityDefine = (Activity)it.next();
            WFActivityInstInternal ai = new WFActivityInstInternal();
            ai.setProcessInstID(processObject.getProcessInstID());
            ai.setActivityDefID(activityDefine.getId());
            OrderCond oc = new OrderCond("activityInstID", 1);
            List list = WFServiceFactory.getService(DataAccessService.class).findBeanList(ai, new PageCond(1), oc, 1);
            if(list.size() == 1)
                activityInsts.add((WFActivityInstInternal)list.get(0));
        }
        
        return (WFActivityInstInternal[])(WFActivityInstInternal[])activityInsts.toArray(new WFActivityInstInternal[activityInsts.size()]);
    }

    private WFActivityInstInternal[] getActInstsFromRunning(ProcessObject processObject)
    {
        WFProcessInstInternal pi = WFServiceFactory.getService(IWFInstancePool.class).findProcessInstanceByID(processObject.getProcessInstID());
        List activityDefines = processObject.getProcess().getActivitys();
        if(pi != null) {
            List ais = new ArrayList();
            Iterator it = activityDefines.iterator();
            while(it.hasNext()){
                Activity activityDefine = (Activity)it.next();
                WFActivityInstInternal activityInst = pi.getProcessInstContext().findLastActInstByDefID(activityDefine.getId());
                if(activityInst != null)
                    ais.add(activityInst);
            }
            return (WFActivityInstInternal[])(WFActivityInstInternal[])ais.toArray(new WFActivityInstInternal[ais.size()]);
        } else{
            return null;
        }
    }

    private WFTransCtrl findTransCtrlInArr(WFTransCtrl transCtrls[], String fromStateID, String toStateID)
    {
        for(int i = 0; i < transCtrls.length; i++)
        {
            WFTransCtrl o = transCtrls[i];
            if(fromStateID.equals(o.getSrcActDefID()) && toStateID.equals(o.getDestActDefID()))
                return o;
        }

        return null;
    }

    private WFTransCtrl[] findAllTransCtrlFromHistory(ProcessObject processObject)throws DataAccessException
    {
        DataAccessService das = WFServiceFactory.getService(DataAccessService.class);
        WFTransCtrl tc = WFTransCtrl.getCriteriaObject();
        tc.setProcessInstID(processObject.getProcessInstID());
        List lst = das.findBeanList(tc, new PageCond(0x7fffffff), 1);
        if(lst == null || lst.size() == 0)
            return new WFTransCtrl[0];
        WFTransCtrl ret[] = new WFTransCtrl[lst.size()];
        for(int i = 0; i < lst.size(); i++)
            ret[i] = (WFTransCtrl)lst.get(i);

        return ret;
    }

    private WFTransCtrl[] findAllTransCtrlFromRunning(ProcessObject processObject)
    {
        WFProcessInstInternal pi = WFServiceFactory.getService(IWFInstancePool.class).findProcessInstanceByID(processObject.getProcessInstID());
        List lst = pi.getProcessInstContext().findAllTransCtrl();
        if(lst == null || lst.size() == 0)
            return new WFTransCtrl[0];
        
        WFTransCtrl ret[] = new WFTransCtrl[lst.size()];
        for(int i = 0; i < lst.size(); i++)
            ret[i] = (WFTransCtrl)lst.get(i);

        return ret;
    }

	public void transform2ProcessInstGraph(List<Connection> list,
			HashMap<String, State> hashMap, ProcessObject processObject) {
		// TODO 自动生成的方法存根
		
	}

	
}
